Skip to content

fix: EgovFixedLengthLineAggregator 멀티스레드 환경 thread-safety 개선#237

Open
z3rotig4r wants to merge 1 commit into
eGovFramework:mainfrom
z3rotig4r:fix/batch-aggregator-thread-safety
Open

fix: EgovFixedLengthLineAggregator 멀티스레드 환경 thread-safety 개선#237
z3rotig4r wants to merge 1 commit into
eGovFramework:mainfrom
z3rotig4r:fix/batch-aggregator-thread-safety

Conversation

@z3rotig4r

Copy link
Copy Markdown
Contributor

개요

EgovFixedLengthLineAggregator(고정길이 출력 라인 집계기)의 paddingList 지연 초기화가 비동기화 상태로 인스턴스에 공유되어, 멀티스레드 step(또는 공유 빈)에서 doAggregate가 동시 호출될 때 thread-safety 문제가 발생합니다.

문제

doAggregate는 다음과 같이 비동기화로 지연 초기화합니다.

if (paddingList == null) {
    createPaddingList();   // paddingList = new ArrayList<>(100)  ← non-null, size 0 먼저 대입 후 채움
}
...
value.append(paddingList.get(needPaddingSize - 1));

createPaddingList()는 빈 리스트를 먼저 필드에 대입한 뒤 루프로 채웁니다. 다른 스레드가 paddingList != null(빈 리스트)을 보고 초기화를 건너뛰면, 부분 초기화된 리스트paddingList.get(...)을 수행하여 다음이 발생할 수 있습니다.

  • 잘못된 폭의 라인 생성 → 고정길이 레코드 정렬이 깨지는 silent 데이터 손상
  • IndexOutOfBoundsException / ConcurrentModificationException

EgovFixedLengthLineAggregatorDefaultItemWriter가 writer당 1개 인스턴스를 생성해 step의 모든 라인 집계에 공유하므로, taskExecutor 기반 멀티스레드 step에서 이 경로에 도달합니다.

변경

가변 공유 상태(paddingList / createPaddingList() / PADDING_LISTSIZE)를 제거하고, 패딩을 String.valueOf(padding).repeat(needPaddingSize)무상태 생성하도록 변경했습니다.

  • 출력 결과 동일(부족한 길이를 padding 문자로 우측 채움)
  • 공유 가변 상태가 없으므로 thread-safe
  • .repeat()는 동일 클래스에서 이미 사용 중이며 Java 11+ 표준 API입니다(본 실행환경 Java 21 타깃)

검증

EgovFixedLengthLineAggregatorTest 6종 추가:

  • 짧은 값 우측 패딩 / 정확한 폭 무변경 / 커스텀 패딩 문자
  • 기존 PADDING_LISTSIZE(100) 분기 경계를 넘는 폭(250) 동작 보존
  • 범위 초과 값 예외(IllegalStateException)
  • 32스레드가 동일 인스턴스를 cold-start 동시 호출하는 동시성 테스트 — 변경 전에는 잘못된 폭 출력이 재현되고, 변경 후 통과

transform 패키지 회귀 테스트 통과(BUILD SUCCESS).

고정길이 라인 집계기의 paddingList 지연 초기화가 비동기화 상태로 공유되어,
멀티스레드 step(또는 공유 빈)에서 doAggregate 동시 호출 시 부분 초기화된
리스트를 참조해 잘못된 폭의 라인을 생성하거나 예외가 발생할 수 있었습니다.

가변 공유 상태(paddingList/createPaddingList/PADDING_LISTSIZE)를 제거하고
패딩을 String.valueOf(padding).repeat(n)로 무상태 생성하도록 변경했습니다.
출력 결과는 동일하며 thread-safe 합니다.

검증: 단위 테스트 6종 추가(우측 패딩/정확폭/커스텀 패딩/100경계 초과/초과값
예외/32스레드 공유 동시성), transform 패키지 회귀 통과.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant